const config = require('./config')

const path = require('path')
// 颜色插件
const chalk = require('chalk')
const gulp = require('gulp')
// 条件判断
const gulpif = require('gulp-if')
// 压缩html代码
const htmlmin = require('gulp-htmlmin')
// 将文件include进来
const fileinclude = require('gulp-file-include')
// sass编译
const sass = require('gulp-sass')
// css处理
const postcss = require('gulp-postcss')
// 压缩css成一行代码
const cleanCSS = require('gulp-clean-css')
// 监控错误
const plumber = require('gulp-plumber')
// 加控制台文字描述用的
const notify = require('gulp-notify')
// 检测文件是否更改
const cache  = require('gulp-cache')
// 图片压缩
const imagemin = require('gulp-imagemin')
// 图片无损压缩
const pngquant = require('imagemin-pngquant')
// 压缩js代码
const uglify = require('gulp-uglify')
// 规范js代码
const eslint = require('gulp-eslint')
// 去掉console.alert这些调试代码
const stripDebug = require('gulp-strip-debug')
// 将es6代码进行转换
const babel = require('gulp-babel')
// 同步执行任务
const sequence = require('gulp-sequence')
// 自动命名并按时间重命名
const zip = require('gulp-zip')
// 删除文件
const del = require('del')

// server
const browserSync = require('browser-sync').create()
const reload = browserSync.reload

// NODE_ENV
const env = process.env.NODE_ENV || 'development'
const condition = env === 'production'

function respath(dir) {
    return path.join(__dirname, './', dir)
}

function onError(error) {
    const title = error.plugin + ' ' + error.name
    const msg = error.message
    const errContent = msg.replace(/\n/g, '\\A ')

    notify.onError({
        title: title,
        message: errContent,
        sound: true
    })(error)

    this.emit('end')
}

function cbTask(task) {
    return new Promise((resolve, reject) => {
        del(respath('dist'))
            .then(paths => {
                console.log(chalk.green(`
      -----------------------------
        Clean tasks are completed
      -----------------------------`))
                sequence(task, () => {
                    console.log(chalk.green(`
        -----------------------------
          All tasks are completed
        -----------------------------`))
                    resolve('completed')
                })
            })
    })
}

// 对html代码进行处理
gulp.task('html', () => {
    return gulp.src(config.dev.html)
        .pipe(plumber(onError))
        .pipe(gulpif(condition, htmlmin({
            removeComments: true,
            collapseWhitespace: true,
            minifyJS: true,
            minifyCSS: true
        })))
        .pipe(gulp.dest(config.build.html))
})

// 对css代码进行处理
gulp.task('styles', () => {
    return gulp.src(config.dev.styles)
        .pipe(plumber(onError))
        .pipe(sass())
        // 判断是不是开发环境，如果不是，那就不进行压缩
        .pipe(gulpif(condition, cleanCSS({debug: true})))
        // 对css进行前缀处理这些
        .pipe(postcss('./.postcssrc.js'))
        .pipe(gulp.dest(config.build.styles))
})

// 对图片进行处理
gulp.task('images', () => {
    return gulp.src(config.dev.images)
        .pipe(plumber(onError))
        .pipe(cache(imagemin({
            progressive: true, // 无损压缩JPG图片
            svgoPlugins: [{removeViewBox: false}], // 不移除svg的viewbox属性
            use: [pngquant()] // 使用pngquant插件进行深度压缩
        })))
        .pipe(gulp.dest(config.build.images))
})

// 添加eslint检测
gulp.task('eslint', () => {
    return gulp.src(config.dev.script)
        .pipe(plumber(onError))
        // 如果是生产环境，就去掉console,debug这些代码
        .pipe(gulpif(condition, stripDebug()))
        .pipe(eslint({ configFle: './.eslintrc' }))
        .pipe(eslint.format())
        .pipe(eslint.failAfterError());
})

// 判断是否进行eslint规范代码
const useEslint = config.useEslint ? ['eslint'] : [];
gulp.task('script', useEslint, () => {
    return gulp.src(config.dev.script)
        // 监控错误
        .pipe(plumber(onError))
        // 使用babel对代码进行转换
        .pipe(gulpif(condition, babel({
            presets: ['env']
        })))
        // 不适用webpack
        // .pipe(gulpif(config.useWebpack, webpackStream(webpackConfig, webpack)))
        .pipe(gulpif(condition, uglify()))
        .pipe(gulp.dest(config.build.script))
})

// 对静态文件进行转移
gulp.task('static', () => {
    return gulp.src(config.dev.static)
        .pipe(gulp.dest(config.build.static))
})

// 清除dist文件夹
gulp.task('clean', () => {
    del('./dist').then(paths => {
        console.log('Deleted files and folders:\n', paths.join('\n'));
    });
})

// 监控文件的变化
// 当这些文件有变化时，执行这些操作
gulp.task('watch', () => {
    gulp.watch(config.dev.allhtml, ['html']).on('change', reload)
    gulp.watch(config.dev.styles, ['styles']).on('change', reload)
    gulp.watch(config.dev.script, ['script']).on('change', reload)
    gulp.watch(config.dev.images, ['images']).on('change', reload)
    gulp.watch(config.dev.static, ['static']).on('change', reload)
})

// 开发环境执行的任务，开启一个服务器
gulp.task('server', () => {
    const task = ['html', 'styles', 'script', 'images', 'static']
    cbTask(task).then(() => {
        browserSync.init(config.server)
        console.log(chalk.cyan('  Server complete.\n'))
        gulp.start('watch')
    })
})

// 生产环境运行的任务
gulp.task('build', () => {
    const task = ['html', 'styles', 'script', 'images', 'static']
    cbTask(task).then(() => {
        console.log(chalk.cyan('  Build complete.\n'))

        if (config.productionZip) {
            gulp.start('zip', () => {
                console.log(chalk.cyan('  Zip complete.\n'))
            })
        }
    })
})

gulp.task('default', () => {
    console.log(chalk.green(
        `
  Build Setup
    开发环境： gulp server
    生产环境： gulp build
    执行压缩： gulp zip
    编译页面： gulp html
    编译脚本： gulp script
    编译样式： gulp styles
    语法检测： gulp eslint
    压缩图片： gulp images
    `
    ))
})